package com.dubbo.rpc.discovery;

import com.dubbo.rpc.common.Constants;
import com.dubbo.rpc.common.LoadBalanceStrategyEnum;
import com.dubbo.rpc.config.ConfigService;
import com.dubbo.rpc.discovery.strategy.AbstractLoadBalanceStrategy;
import com.dubbo.rpc.discovery.strategy.RandomStrategy;
import com.dubbo.rpc.domain.ProviderInfo;
import com.dubbo.rpc.domain.ServiceDiscoveryInfo;
import org.I0Itec.zkclient.ZkClient;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

/**
 * 服务发现
 *
 * @author liuxin
 * @date 2021/10/10 9:44
 */
@Component
public class ServiceDiscovery {

    @Resource
    private ConfigService configService;

    @Resource
    private LoadBalanceStrategyFactory loadBalanceStrategyFactory;


    public String discover(String name) {
        ZkClient zkClient = new ZkClient(configService.getZkHost(), Constants.ZK_SESSION_TIME_OUT, Constants.ZK_CONNECTION_TIME_OUT);

        try {
            String servicePath = Constants.ZK_REGISTRY_PATH + Constants.ZK_PATH_DELIMITER + name;
            if (!zkClient.exists(servicePath)) {
                throw new RuntimeException("can't find servicePath " + servicePath);
            }

            List<String> addressList = zkClient.getChildren(servicePath);
            if (CollectionUtils.isEmpty(addressList)) {
                throw new RuntimeException("can't find servicePath " + servicePath);
            }

            String address = selectAddress(addressList);
            String addressPath = servicePath + Constants.ZK_PATH_DELIMITER + address;

            return zkClient.readData(addressPath);
        } finally {
            zkClient.close();
        }
    }

    /**
     * 从众多地址中选取一个调用
     *
     * @param addressList
     * @return
     */
    private String selectAddress(List<String> addressList) {
        ServiceDiscoveryInfo serviceDiscoveryInfo = parse(addressList);
        ProviderInfo providerInfo = selectProvider(serviceDiscoveryInfo);

        System.err.println(addressList.get(0));
        return addressList.get(0);
    }


    /**
     * 解析
     * @param addressList
     * @return
     */
    private ServiceDiscoveryInfo parse(List<String> addressList) {
        return null;
    }

    private ProviderInfo selectProvider(ServiceDiscoveryInfo serviceDiscoveryInfo) {
        AbstractLoadBalanceStrategy strategy = loadBalanceStrategyFactory.selectStrategy(serviceDiscoveryInfo.getLoadBalanceStrategy());
        return new LoadbalanceContext(strategy).executeStrategy(serviceDiscoveryInfo);
    }

}
